package ua.abihle.aichallenge;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import ua.abihle.basic.Aim;
import ua.abihle.basic.Ants;
import ua.abihle.basic.Bot;
import ua.abihle.basic.Tile;

public class FindFoodFirstStrategy implements IStrategy {
	private Bot bot;
	private Set<Tile> freeAnts = new HashSet<Tile>();
	private Set<AntTask> busyAnts = new HashSet<AntTask>();
	private Set<Target> curTargets = new HashSet<Target>();
	private Map<Tile, Tile> orders  = new HashMap<Tile, Tile>();
	private PathFinder pathFinder = new PathFinder();

	public FindFoodFirstStrategy(Bot bot) {
		this.bot = bot;		
	}

	public void setBot(Bot bot) {
		this.bot = bot;
	}

	private void findFreeAnts() {
		freeAnts.clear();
		for (Tile t : bot.getAnts().getMyAnts())
			if (!busyAnts.contains(t))
				freeAnts.add(t);
	}

	private void proceedCurrentTasks() {
		orders.clear();
		for(AntTask at: busyAnts){
			Set<Aim> aims = pathFinder.getDirection(at);
			for(Aim aim: aims){
				Tile trg = bot.getAnts().getTile(at.getAnt(), aim);
				if(!orders.values().contains(trg)){
					orders.put(at.getAnt(), trg);
					bot.getAnts().issueOrder(at.getAnt(), aim);
					break;
				}
			}
		}
	}
	
	private void checkTasksValidity(){
		for(Iterator<AntTask> i = busyAnts.iterator(); i.hasNext();)
			if(!i.next().validate())
				i.remove();
	}

	private void proceedTargets(List<Target> targets) {
		targets.removeAll(curTargets);
		for (Target trgt : targets) {
			if (freeAnts.isEmpty())
				break;
			Tile ant = Util.findNearestAnt(trgt.getLocation(), freeAnts, bot.getAnts());
			freeAnts.remove(ant);
			AntTask task = new AntTask(ant, trgt, bot.getAnts());
			busyAnts.add(task);
		}
	}

	@Override
	public void doTurn() {
		pathFinder.setAnts(bot.getAnts());
		
		
		checkTasksValidity();
		
		curTargets.clear();
		for(AntTask at: busyAnts)
			curTargets.add(at.getTarget());
		
		findFreeAnts();
		if (freeAnts.isEmpty()) {
			proceedCurrentTasks();
			return;
		}

		List<Target> targets = FindTargetsService.getFindFoodFirstTargets(bot.getAnts());
		proceedTargets(targets);
		
		proceedCurrentTasks();
	}

}
